package com.matrix.draft.sockettest.newprotocoltcp.handler;

import cn.hutool.core.util.ObjectUtil;
import com.matrix.draft.sockettest.newprotocoltcp.pojo.MyMessage;
import com.matrix.draft.sockettest.newprotocoltcp.pojo.StringMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 解码器
 */
@Slf4j
public class NewProtocolDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        /** LengthFieldBasedFrameDecoder中并没有剥离任何数据(注意readInt和readByte的使用) **/
        /**
         * 由于各种头信息我们需要注入到XXXMessage中, 方便后面取用
         * 所以LengthFieldBasedFrameDecoder不要设置剥离任何数据
         */
        // 魔数 (判定数据包是否是符合标准的有效的, 4b)
        // 版本号 (可以支持协议升级, 1b)
        // 序列化算法 (json,protobuf,hessian,jdk, 4b)
        // 指令类型 (例如登录,注册,群聊,私聊等业务相关, 4b)
        // 请求序号 (为了双工通信提供异步能力, 4b)
        // ###如果前面的字段的长度加起来不是2的倍数,这里再writeByte(0xff)一个字节(无意义)###
        // 正文长度字段 (4b)
        // 正文
        int magicNum = in.readInt();
        byte version = in.readByte();
        int serializationType = in.readInt();
        int affairType = in.readInt();
        int sequenceId = in.readInt();
        in.readByte(); // 凑字节数的无用信息
        int len = in.readInt();
        byte[] bytes = new byte[len];
        in.readBytes(bytes);
        // 根据affairType创建不同的MyMessage的子类
        MyMessage myMessage;
        switch (affairType) {
            // 1:STRING
            default:
            case 1: {
                myMessage = new StringMessage(new String(bytes));
                break;
            }
        }
        if (ObjectUtil.isNull(myMessage)) {
            throw new RuntimeException("affairType错误, 请按照规范来");
        }
        myMessage
                .setMagicNum(magicNum)
                .setVersion(version)
                .setSerializationType(serializationType)
                .setAffairType(affairType)
                .setSequenceId(sequenceId)
                .setLen(len);
        out.add(myMessage);
        log.debug("Decoded");
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
